package com.ruoyi.system.service.impl.fxImpl;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.dto.FxStoreGoodDto;
import com.ruoyi.system.domain.fx.*;
import com.ruoyi.system.domain.vo.FxStoreGoodVo;
import com.ruoyi.system.domain.vo.PortalSearchVo;
import com.ruoyi.system.mapper.fx.*;
import com.ruoyi.system.service.fx.IFxStoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.ruoyi.common.constant.Constants.FX_COM;
import static com.ruoyi.common.constant.Constants.HTTPS;
import static com.ruoyi.common.utils.CodeGeneratorUtil.createQrCode;
import static com.ruoyi.common.utils.PageUtils.startPage;


/**
 * 门店Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-23
 */
@Service
public class FxStoreServiceImpl implements IFxStoreService {
    @Autowired
    private FxStoreMapper fxStoreMapper;
    @Autowired
    private FxTagMapper fxTagMapper;
    @Autowired
    private FxStoreGoodMapper fxStoreGoodMapper;
    @Autowired
    private FxChinaMapper fxChinaMapper;
    @Autowired
    private FxUserMapper fxUserMapper;
    @Autowired
    private FxToJoinMapper fxToJoinMapper;

    // 纬度验证正则表达式
    private static final String LATITUDE_PATTERN = "^[-+]?((90(\\.\\d{1,6})?)|([1-8]?\\d(\\.\\d{1,6})?))$";

    // 经度验证正则表达式
    private static final String LONGITUDE_PATTERN = "^[-+]?((180(\\.\\d{1,6})?)|((1[0-7]\\d)|([1-9]\\d?))(\\.\\d{1,6})?)$";

    /**
     * 查询门店
     *
     * @param id 门店主键
     * @return 门店
     */
    @Override
    public FxStore selectFxStoreById(Long id) {
        FxTag fxTags = new FxTag();
//        fxTags.setType("3"); // 3门店标签
        // 获取门店标签
        List<FxTag> tags = fxTagMapper.selectFxTagList(fxTags);
        Map<Long, FxTag> tagMap = tags.stream().collect(Collectors.toMap(FxTag::getId, fxTag -> fxTag));
        FxToJoin fxToJoin = fxToJoinMapper.selectToJoinByStoreId(id);
        FxStore store = Optional.ofNullable(fxStoreMapper.selectFxStoreById(id))
                .map(s -> {s.setLicenseImg(fxToJoin.getLicenseImg()); return s;}).orElse(null);
        if(StringUtils.isNotNull(store) && StringUtils.isNotEmpty(store.getStoreTags())){
            String[] tagIds = store.getStoreTags().split(",");
            List<FxTag> fxTagList = Arrays.stream(tagIds).distinct()
                    .map(tagId -> tagMap.get(Long.valueOf(tagId)))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            List<FxTag> tagList = fxTagList.stream()
                    .filter(tag -> tag.getType().equals("3")).collect(Collectors.toList());

            List<FxTag> typeList = fxTagList.stream()
                    .filter(tag -> tag.getType().contains("2")).collect(Collectors.toList());

            String tagNames = tagList.stream()
                    .map(FxTag::getTagName)
                    .collect(Collectors.joining(","));
            String typeNames = typeList.stream()
                    .map(FxTag::getTagName)
                    .collect(Collectors.joining(","));
            String ids = tagList.stream()
                    .map(tag -> String.valueOf(tag.getId()))
                    .collect(Collectors.joining(","));
            String typeTagIds = typeList.stream()
                    .map(tag -> String.valueOf(tag.getId()))
                    .collect(Collectors.joining(","));
            store.setTegNames(tagNames);
            store.setTypeTag(typeNames);
            store.setTagIds(ids);
            store.setTypeTagIds(typeTagIds);
        }else {
            store.setStoreTags(null);
        }
        return store;
    }

    /**
     * 查询门店列表
     *
     * @param fxStore 门店
     * @return 门店
     */
    @Override
    public List<FxStore> selectFxStoreList(FxStore fxStore) {
        Long userId = SecurityUtils.getUserId();
        List<Long> roles = SecurityUtils.getLoginUser().getUser().getRoles()
                .stream().map(SysRole::getRoleId).collect(Collectors.toList());
        FxUser fxUser = new FxUser();
        fxUser.setSysUserid(userId);
        List<FxUser> userList = fxUserMapper.selectFxUserList(fxUser);
        // 获取全部门店
        startPage();
        List<FxStore> stores = new ArrayList<>();
        if (roles.contains(1L) || roles.contains(6L)){
            stores = fxStoreMapper.selectFxStoreList(fxStore);
        }
        if (roles.contains(4L)) { // 是店铺
            Integer storeId = Convert.toInt(userList.get(0).getStoreId());
            List<Integer> ids = new ArrayList<>();
            ids.add(storeId);
            stores = fxStoreMapper.selectFxStoreListByIds(ids);
        } else if (roles.contains(3L)){ // 是供应商
            return stores;
        }

        FxTag fxTags = new FxTag();
//        fxTags.setType("3"); // 3门店标签
        // 获取门店标签
        List<FxTag> tags = fxTagMapper.selectFxTagList(fxTags);
        Map<Long, FxTag> tagMap = tags.stream().collect(Collectors.toMap(FxTag::getId, fxTag -> fxTag));
        for (FxStore store : stores) {
            if (StringUtils.isNotEmpty(store.getStoreTags())) {
                String[] tagIds = store.getStoreTags().split(",");
                List<FxTag> fxTagList = Arrays.stream(tagIds).distinct()
                        .map(tagId -> tagMap.get(Long.valueOf(tagId)))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                List<FxTag> tagList = fxTagList.stream()
                        .filter(tag -> tag.getType().equals("3")).collect(Collectors.toList());

                List<FxTag> typeList = fxTagList.stream()
                        .filter(tag -> tag.getType().contains("2")).collect(Collectors.toList());

                String tagNames = tagList.stream()
                        .map(FxTag::getTagName)
                        .collect(Collectors.joining(","));
                String typeNames = typeList.stream()
                        .map(FxTag::getTagName)
                        .collect(Collectors.joining(","));
                String ids = tagList.stream()
                        .map(tag -> String.valueOf(tag.getId()))
                        .collect(Collectors.joining(","));
                String typeTagIds = typeList.stream()
                        .map(tag -> String.valueOf(tag.getId()))
                        .collect(Collectors.joining(","));
                store.setTegNames(tagNames);
                store.setTypeTag(typeNames);
                store.setTagIds(ids);
                store.setTypeTagIds(typeTagIds);
            }
        }
        return stores;
    }

    /**
     * 首页搜索
     *
     * @param search
     * @return
     */
    @Override
    public PortalSearchVo portalSearch(String cityString, String search, String longitude, String latitude) {
        // 收索框未输入 返回空对象
        PortalSearchVo portalSearchVo = new PortalSearchVo();

        // 设入 搜索内容 , 经纬度
        FxStore fxStore = new FxStore();
        fxStore.setStoreName(search);
        fxStore.setLongitude(longitude);
        fxStore.setLatitude(latitude);
        fxStore.setCityString(cityString);
        fxStore.setIsInitiate(0L);
        // 查询门店 按距离 升序
        Collection<FxStore> storeCollection = this.selectFxStoreListApp(fxStore);

        if (StringUtils.isNotEmpty(storeCollection)) {
            portalSearchVo.setStoresList(new ArrayList<>(storeCollection));
        }

        if (StringUtils.isEmpty(search)) {
            return portalSearchVo;
        }

        // 创建 门店商品对象 设入 搜索内容
        FxStoreGoodDto fxStoreGoodDto = new FxStoreGoodDto();
        fxStoreGoodDto.setGoodName(search);
        // 查询商品 只取前十
        List<FxStoreGoodVo> storeGoodVoList = fxStoreGoodMapper.selectAppGoodList(fxStoreGoodDto);
        // 判断 商品列表是否为空
        if (StringUtils.isNotEmpty(storeGoodVoList)) {
            // 取商品列表对象 id 组成新集合
            List<Integer> storeId = storeGoodVoList.stream().map(FxStoreGoodVo::getStoreId).distinct().collect(Collectors.toList());

            // 设入 门店id集合 当前经纬度
            fxStore.setIds(storeId);
            fxStore.setLongitude(longitude);
            fxStore.setLatitude(latitude);
            fxStore.setStoreName(null);
            // 查询门店 按距离 升序
            Collection<FxStore> fxStoreCollection = Optional.ofNullable(this.selectFxStoreListApp(fxStore))
                    .orElse(new ArrayList<>());
            // 设入 返回
            portalSearchVo.getStoresList().addAll(fxStoreCollection);
//            Map<Long, FxStore> storeMap = fxStoreCollection.stream().collect(Collectors.toMap(FxStore::getId, store -> store));
//            // 循环设置 门店名称及距离
//            for (FxStoreGoodVo storeGoodVo : storeGoodVoList) {
//                FxStore store = storeMap.get(storeGoodVo.getStoreId().longValue());
//                storeGoodVo.setStoreName(store.getStoreName());
//                storeGoodVo.setDistance(Double.parseDouble(store.getDistance()));
//            }
//            // 排序 按距离 升序
//            storeGoodVoList = storeGoodVoList.stream()
//                    .sorted(Comparator.comparingDouble(FxStoreGoodVo::getDistance))
//                    .collect(Collectors.toList());
            portalSearchVo.setStoresList(
                    portalSearchVo.getStoresList().stream()
                            .collect(Collectors.toMap(FxStore::getId,store -> store))
                            .values()
                            .stream()
                            .sorted(Comparator.comparingDouble(store -> Double.parseDouble(store.getDistance())))
                            .collect(Collectors.toList())
            );
        }
        // 设入 返回
//        portalSearchVo.setStoreGoodList(storeGoodVoList);
        return portalSearchVo;
    }

    /**
     * 新增门店
     *
     * @param fxStore 门店
     * @return 结果
     */
    @Override
    public int insertFxStore(FxStore fxStore) {

        if (!fxStore.getLongitude().matches(LONGITUDE_PATTERN)) {
            throw new GlobalException("经度格式错误，创建门店失败！");
        }
        if (!fxStore.getLatitude().matches(LATITUDE_PATTERN)) {
            throw new GlobalException("纬度格式错误，创建门店失败！");
        }

        if (StringUtils.isEmpty(fxStore.getStoreTags()))
            throw new GlobalException("门店标签未选择");
        // 判断经纬度 是否为空
        if (StringUtils.isEmpty(fxStore.getLongitude()) || StringUtils.isEmpty(fxStore.getLatitude()))
            throw new GlobalException("该门店地址未知，创建门店失败");
        // 查询门店名称是否存在
        FxStore selectZyStore = new FxStore();
        selectZyStore.setStoreName(fxStore.getStoreName());
        List<FxStore> zyStores = fxStoreMapper.selectFxStoreList(selectZyStore);
        if (StringUtils.isNotEmpty(zyStores))
            throw new GlobalException("该门店名称已存在，创建门店失败！");

        // 插入省市区
        List<Long> addressAll = fxStore.getAddressAll();
        if (StringUtils.isNotEmpty(addressAll)) {
            fxStore.setProvince(addressAll.get(0));
            fxStore.setProvinceString(fxChinaMapper.selectFxChinaById(addressAll.get(0)).getCityName());
            fxStore.setCity(addressAll.get(1));
            fxStore.setCityString(fxChinaMapper.selectFxChinaById(addressAll.get(1)).getCityName());
            fxStore.setRegion(addressAll.get(2));
            fxStore.setRegionString(fxChinaMapper.selectFxChinaById(addressAll.get(2)).getCityName());
        }
        // TODO 判断店铺标签与类型标签是否不为空
        if (StringUtils.isNotEmpty(fxStore.getTagIds()) || StringUtils.isNotEmpty(fxStore.getTypeTagIds())) {
            fxStore.setStoreTags(fxStore.getTagIds() + fxStore.getTypeTagIds());
        }

        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        // 将日期格式化为指定格式的字符串
        String formattedDate = currentDate.format(formatter);
        // 上传文件路径
        String filePath = RuoYiConfig.getUploadPath() + "/storeBarCode/" + formattedDate;
        String url = HTTPS + FX_COM + "/dist?storeId="+fxStore.getId();
        String qrCodeImgPath = createQrCode(url, filePath);
        String imgUrl = "/profile/upload/storeBarCode/" + formattedDate + qrCodeImgPath;
        fxStore.setStoreQrCodeUrl(imgUrl); //分销二维码
        fxStore.setCreateTime(DateUtils.getNowDate());
        return fxStoreMapper.insertFxStore(fxStore);
    }

    /**
     * 修改门店
     *
     * @param fxStore 门店
     * @return 结果
     */
    @Override
    public int updateFxStore(FxStore fxStore) {
//        if (StringUtils.isEmpty(fxStore.getStoreTags()))
//            /throw new GlobalException("门店标签未选择");
        if (!fxStore.getLongitude().matches(LONGITUDE_PATTERN)) {
            throw new GlobalException("经度格式错误，创建门店失败！");
        }
        if (!fxStore.getLatitude().matches(LATITUDE_PATTERN)) {
            throw new GlobalException("纬度格式错误，创建门店失败！");
        }
        // 修改省市区
        List<Long> addressAll = fxStore.getAddressAll();
        if (StringUtils.isNotEmpty(addressAll)) {
            if (!Objects.equals(fxStore.getProvince(), addressAll.get(0))) {
                fxStore.setProvince(addressAll.get(0));
                fxStore.setProvinceString(fxChinaMapper.selectFxChinaById(addressAll.get(0)).getCityName());
            } else if (!Objects.equals(fxStore.getCity(), addressAll.get(1))) {
                fxStore.setCity(addressAll.get(1));
                fxStore.setCityString(fxChinaMapper.selectFxChinaById(addressAll.get(1)).getCityName());
            } else if (!Objects.equals(fxStore.getRegion(), addressAll.get(2))) {
                fxStore.setRegion(addressAll.get(2));
                fxStore.setRegionString(fxChinaMapper.selectFxChinaById(addressAll.get(2)).getCityName());
            }
        }
        // 查询门店名称是否存在
        FxStore selectZyStore = new FxStore();
        selectZyStore.setStoreName(fxStore.getStoreName());
        List<FxStore> zyStores = fxStoreMapper.selectExistStores(selectZyStore);
        if (zyStores.size()>0)
            throw new GlobalException("该门店名称已存在，修改门店失败！");
        fxStore.setUpdateTime(DateUtils.getNowDate());
        FxToJoin fxToJoin = fxToJoinMapper.selectToJoinByStoreId(fxStore.getId());
        if (StringUtils.isNotNull(fxToJoin)) {
            fxToJoin.setStoreName(fxStore.getStoreName());
            fxToJoin.setAddress(fxStore.getDetail());
            fxToJoin.setPhone(fxStore.getPhoneNumber());
            fxToJoin.setImg(fxStore.getImages());
            fxToJoin.setLicenseImg(fxStore.getLicenseImg());
            fxToJoinMapper.updateFxToJoin(fxToJoin);
        }
        return fxStoreMapper.updateFxStore(fxStore);
    }

    @Override
    public int updateFxStoreByIds(Long[] ids) {
        return fxStoreMapper.updateFxStoreByIds(ids);
    }

    /**
     * 批量删除门店
     *
     * @param ids 需要删除的门店主键
     * @return 结果
     */
    @Override
    public int deleteFxStoreByIds(Long[] ids) {
        return fxStoreMapper.deleteFxStoreByIds(ids);
    }

    /**
     * 删除门店信息
     *
     * @param id 门店主键
     * @return 结果
     */
    @Override
    public int deleteFxStoreById(Long id) {
        return fxStoreMapper.deleteFxStoreById(id);
    }

    /**
     * 禁用门店
     *
     * @param fxStore
     * @return
     */
    @Override
    public int forbidden(FxStore fxStore) {
        FxStore store = fxStoreMapper.selectFxStoreById(fxStore.getId());
        if (StringUtils.isNull(store)) {
            throw new GlobalException("门店信息错误");
        }
        store.setForbidden(fxStore.getForbidden());
        store.setUpdateTime(fxStore.getUpdateTime());
        store.setIsInitiate(1L == fxStore.getForbidden() ? 1L : 0L);
        fxStoreMapper.updateFxStore(store);
        // 查询用户 修改状态
        Long userStatus = 1L == fxStore.getForbidden() ? 1L : 0L;
        return fxStoreMapper.forbiddenStore(store.getId(),userStatus);
    }

    /**
     * 小程序 门店排序
     *
     * @param fxStore
     * @return
     */
    @Override
    public Collection<FxStore> selectFxStoreListApp(FxStore fxStore) {
        //获取经纬度
        String longitude = fxStore.getLongitude();
        String latitude = fxStore.getLatitude();

        fxStore.setLongitude(null);
        fxStore.setLatitude(null);
        //查询当前城市所在有所门店
        List<FxStore> zyStores = new ArrayList<FxStore>();
        if (StringUtils.isNotEmpty(fxStore.getIds())) {
            zyStores = fxStoreMapper.selectFxStoreListByIds(fxStore.getIds());
        } else {
            zyStores = fxStoreMapper.selectFxStoreList(fxStore);
        }
        if (zyStores.size() == 0)
            return null;
        // 查找门店标签
        FxTag fxTags = new FxTag();
        fxTags.setType("3"); // 3门店标签
        List<FxTag> tags = fxTagMapper.selectFxTagList(fxTags);
        // 标签转为map id为key
        Map<Long, FxTag> tagMap = tags.stream().collect(Collectors.toMap(FxTag::getId, fxTag -> fxTag));

        // 循环插入门店标签
        zyStores.forEach(store -> {
            if (StringUtils.isNotEmpty(store.getStoreTags())) {
                // 门店标签id
                Long[] tagIds = Convert.toLongArray(store.getStoreTags());
                // 循环id
                String tagNames = Arrays.stream(tagIds)
                        .map(tagMap::get)// 拿到当前id value值
                        .filter(Objects::nonNull)// 过滤掉为空的
                        .map(FxTag::getTagName) // 取value值中的tagName
                        .collect(Collectors.joining(","));// 以逗号拼接
                store.setTegNames(tagNames);// 写入门店
            }
        });
        // 经纬度为空 不排序直接返回
        if (ObjectUtils.isEmpty(longitude) || ObjectUtils.isEmpty(latitude)) {
            return zyStores;
        }

        //门店按照距离排序
        TreeMap<Double, FxStore> doubleZyStoreTreeMap = new TreeMap<>();
        int i=0;
       for(FxStore zyStore1: zyStores){
           i++;
           double distance = calculateDistance(Double.parseDouble(latitude), Double.parseDouble(longitude), Double.parseDouble(zyStore1.getLatitude()), Double.parseDouble(zyStore1.getLongitude()));
           if (doubleZyStoreTreeMap.containsKey(distance))
               distance += 0.01*i;

           if (StringUtils.isNotEmpty(fxStore.getCityString())) {
               //把距离和商家一起 key是距离，value是商家
               doubleZyStoreTreeMap.put(distance, zyStore1);
           }else {
               if(distance <= 5000){
                   //把距离和商家一起 key是距离，value是商家
                   doubleZyStoreTreeMap.put(distance, zyStore1);
               }
           }
           DecimalFormat decimalFormat = new DecimalFormat("#.##"); // 设置保留一位小数的格式
//            String formattedDistance = decimalFormat.format(distance) + "m"; // 默认单位m
//            if (distance > 1000) //距离超过1km 单位调整为km
//                formattedDistance = decimalFormat.format((distance / 1000)) + "km"; // 对double进行计算并格式化输出结果
           String formattedDistance = decimalFormat.format(distance / 1000);
           zyStore1.setDistance(formattedDistance);
       }
        return doubleZyStoreTreeMap.values();
    }

    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        // 将经纬度转换为弧度
        double radLat1 = Math.toRadians(lat1);
        double radLon1 = Math.toRadians(lon1);
        double radLat2 = Math.toRadians(lat2);
        double radLon2 = Math.toRadians(lon2);

        // Haversine公式计算距离
        double a = Math.sin((radLat2 - radLat1) / 2) * Math.sin((radLat2 - radLat1) / 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.sin((radLon2 - radLon1) / 2) * Math.sin((radLon2 - radLon1) / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = 6371000 * c; // 单位：米

        return distance;
    }
}
